home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
graphics
/
vlapak1.zip
/
TSR_VLA.ZIP
/
TSR.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-08-19
|
10KB
|
331 lines
IDEAL
MODEL Tiny ;TINY, cause we are making a COM file
────────────────────────────────────────────────────────────────────────────
CODESEG
LOCALS
P386n
MASM
.STARTUP ;in a COM file, CS = SS = DS = ES = PSPseg at startup
;I used .STARTUP here cause I couldn't get it
;to do a com file otherwise... =(
IDEAL
mov sp,offset StackArea + 200h ;setup 200h byte stack (for setup
; only!)
jmp Init_TSR ;Start TSR!
────────────────────────────────────────────────────────────────────────────
; We put all our PERMANENT data right here...
────────────────────────────────────────────────────────────────────────────
MultiIdent = 0D7h ;our identifier - can be any value >= D7h?
ENVoff = 2ch ;offset in PSP seg to ENVironment block seg
TrueCode = 0fed8h ;a double check to make sure it's our guy
; that's installed
PSPseg dw ? ;ES at the beginning of execution
OldInt10h dd ? ;intercept BIOS calls to detect mode changes
OldInt1Ch dd ? ;this is called by timer interrupt 8 (IRQ 0)
OldInt2fh dd ? ;this is the old multi-plex interrupt
TimerActive db 2 ;0= do nothing, not in TEXT video mode
;1= display time and message.
Other_Stack dd ? ;save stack SS:SP here
Our_Stack dd ?
────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────
; This new Int 10h is just to detect mode changes
────────────────────────────────────────────────────────────────────
PROC Int_10h FAR
pushf
call [DWORD CS:OldInt10h] ;execute the interrupt
mov [cs:TimerActive],0 ;assume it GRAPH mode
push ds bx
xor bx,bx
mov ds,bx
mov bl,[ds:449h] ;get video mode
cmp bl,3
ja short @@IsGraph
mov [cs:TimerActive],1
@@IsGraph:
pop bx ds
iret
ENDP
────────────────────────────────────────────────────────────────────
; This Int 1Ch handler does all the dirty work
────────────────────────────────────────────────────────────────────
PROC Int_1Ch FAR
cmp [CS:TimerActive],0
je @@END
cli ;an interrupt MAY crash the computer...
; cause we're messing with the stack
mov [WORD HIGH cs:Other_Stack],ss ;setup our stack
mov [WORD LOW cs:Other_Stack],sp
lss sp,[cs:Our_Stack]
push es cx ax dx di
cld
mov ax,0b800h
mov es,ax
mov di,(80-8) * 2 ;upper right side
mov ah,2 ;read real time clock
int 1ah ;CH = hours in BCD
;CL = minutes, DH= seconds
mov ah,021h ;color blue on green (LAME!)
mov al,ch
shr al,4
add al,"0"
stosw
mov al,ch ;print hours
and al,00001111b
add al,"0"
stosw
mov al,":"
stosw
mov al,cl
shr al,4
add al,"0"
stosw
mov al,cl ;print minutes
and al,00001111b
add al,"0"
stosw
mov al,":"
stosw
mov al,dh
shr al,4
add al,"0"
stosw
mov al,dh ;print seconds
and al,00001111b
add al,"0"
stosw
pop di dx ax cx es
lss sp,[cs:Other_Stack] ;restore other guys stack
sti
@@END:
jmp [DWORD cs:OldInt1Ch] ;do original interrupt
ENDP
────────────────────────────────────────────────────────────────────
; call Int 2Fh with AH = MultiIdent and you will get back...
;
; If TSR is installed...
;OUT: CF= 0
; AX= TRUECODE
; BX= PSP seg (use to release memory block)
; CX= CS (use to access variables)
;
; If TSR was NOT previously installed...
;OUT: AH= <unchanged>
; CF= 1
────────────────────────────────────────────────────────────────────
PROC Int_2Fh FAR
cmp ah,MultiIdent ;is it our call?
je short @@Its_Ours
jmp [DWORD cs:OldInt2Fh] ;nope, let it chain through
@@Its_Ours:
mov ax,TrueCode ;tell 'em that it's REALLY ours
mov bx,[cs:PSPseg] ;grab PSP segment
mov cx,cs ;set to current CODESEG
clc
retf 2 ;need flags to NOT be restored
ENDP
dw 50 dup (?) ;a VERY small stack.. enough to push all
;extended registers and segment regs..
LABEL The_Stack WORD ;!!! NOTE THAT THE LABEL IS AFTER THE STACK !!!
; STACKS GO DOWN!!
────────────────────────────────────────────────────────────────────────────
; !!!! EXERYTHING ABOVE THIS POINT REMAINS RESIDENT. BELOW GOES BYEBYE !!!!
────────────────────────────────────────────────────────────────────────────
AXE_POINT: ;where we chop the code.. =)
────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────
; We put all our SETUP-ONLY data right here...
────────────────────────────────────────────────────────────────────────────
MSG_Installed db "TSR was successfully installed.",13,10,0
MSG_Removed db "TSR is now removed.",13,10,0
────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────
; Prints a ASCIIZ string pointed to by DS:SI
────────────────────────────────────────────────────────────────────
PROC PrintZ NEAR
push si ax dx
@@PrLoop:
mov dl,[si]
inc si
or dl,dl
je short @@Done
mov ah,2
int 21h
jmp short @@PrLoop
@@Done:
pop dx ax si
ret
ENDP
────────────────────────────────────────────────────────────────────
; Initializes the TSR or, if it's already installed, removes it.
────────────────────────────────────────────────────────────────────
PROC Init_TSR NEAR
mov ax,cs
mov ds,ax
mov [PSPseg],es ;save PSPseg
mov [WORD LOW Our_Stack],offset The_Stack ;setup our stack
mov [WORD HIGH Our_Stack],cs
mov ah,MultiIdent ;check to see if we are already installed
int 2fh
jc short @@Install ;not there
cmp ax,TrueCode ;is it REALLY installed?
jne short @@Install
push bx ;BX = PSPseg of other guy
──
push ds
mov ds,cx ;DS = other guys CS
mov bx,10h ;uninstall other guys stuff
mov di,offset OldInt10h ;use same offsets, since it's the same
call Restore_int ; program... =)
mov bx,1ch
mov di,offset OldInt1ch
call Restore_int
mov bx,2fh
mov di,offset OldInt2fh
call Restore_int
pop ds
──
pop es ;from BX's push.. get the PSPseg of OTHER GUY
mov ah,49h
int 21h ;release that memory block
mov ax,cs
mov ds,ax
mov si,offset Msg_Removed
call PrintZ
mov ax,4c00h
int 21h ;exit program
@@Install:
mov es,[cs:ENVoff] ;get segment of Environment block
mov ah,49h
int 21h ;release it (WE DON'T NEED IT)
──
mov ax,cs
mov ds,ax
mov bx,10h
mov di,offset OldInt10h
mov dx,offset Int_10h
call Set_Int
mov bx,1ch
mov di,offset OldInt1ch
mov dx,offset Int_1ch
call Set_Int
mov bx,2fh
mov di,offset OldInt2fh
mov dx,offset Int_2fh
call Set_Int
──
mov si,offset MSG_Installed
call PrintZ
──
mov dx,offset AXE_Point
shr dx,4
inc dx
mov ax,3100h ;function KEEP (advanced TSR)
int 21h ; al = return code, dx = paragraphs to keep
ENDP
────────────────────────────────────────────────────────────────────
; bx = interrupt # to replace
;
;DS:DI = where to store old interrupt
;DS:DX = offset to new INTerrupt
────────────────────────────────────────────────────────────────────
PROC Set_Int NEAR
push es ecx bx
xor cx,cx
mov es,cx
shl bx,2
mov ecx,[es:bx] ;grab old int
mov [di],ecx ;save it
cli
mov [WORD es:bx ],dx ;store new int
mov [WORD es:bx+2],ds
sti
pop bx ecx es
ret
ENDP
────────────────────────────────────────────────────────────────────
; bx = interrupt # to restore
;
;DS:DI = where old interrupt is stored
────────────────────────────────────────────────────────────────────
PROC Restore_Int NEAR
push es ecx bx
xor cx,cx
mov es,cx
shl bx,2
cli
mov ecx,[di] ;grab old SAVED int
mov [es:bx],ecx ;restore it
sti
pop bx ecx es
ret
ENDP
StackArea: ;where the stack for initialization goes
END